6.1 内存存储

本节所说的内存存储指的是将数据存储在运行中的应用里面,并在应用运行的过程中使用这些数据,而不是说将数据存储到内存数据库里面。将数据存储在数据结构里面是实现内存存储的常见手段,对于Go语言来说,这意味着使用数组、切片、映射和结构来存储数据。

存储数据这一操作本身是非常简单的,用户只需要创建相应的结构、切片和映射就可以了。但如果我们更加深入地思考这个问题就会发现,程序最终操作的将不是一个个单独的结构,而是一系列由容器(container)包裹的多个结构:这些容器既可以是数组、切片和映射,也可以是栈、树、队列以及其他任意类型的数据结构。

除容器本身之外,如何从容器里面获取所需的数据也是一个非常有趣的问题。比如说,代码清单6-1就展示了一个使用映射作为结构容器的例子。

代码清单6-1 在内存里面存储数据

package main
import (
  "fmt"
)
type Post struct {
  Id   int
  Content string
  Author string
}
var PostById map[int]*Post
var PostsByAuthor map[string][]*Post
func store(post Post) {
  PostById[post.Id] = &post
  PostsByAuthor[post.Author] = append(PostsByAuthor[post.Author], &post)
}
func main() {
  PostById = make(map[int]*Post)
  PostsByAuthor = make(map[string][]*Post)
  post1 := Post{Id: 1, Content: "Hello World!", Author: "Sau Sheong"}
  post2 := Post{Id: 2, Content: "Bonjour Monde!", Author: "Pierre"}
  post3 := Post{Id: 3, Content: "Hola Mundo!", Author: "Pedro"}
  post4 := Post{Id: 4, Content: "Greetings Earthlings!", Author:
  ➥"Sau Sheong"}
  store(post1)
  store(post2)
  store(post3)
  store(post4)
  fmt.Println(PostById[1])
  fmt.Println(PostById[2])
  for _, post := range PostsByAuthor["Sau Sheong"] {
    fmt.Println(post)
  }
  for _, post := range PostsByAuthor["Pedro"] {
    fmt.Println(post)
  }
}

这个程序会使用 Post 结构来表示论坛应用中的帖子,并将该结构存储在内存里面:

type Post struct {
  Id   int
  Content string
  Author string
}

Post 结构中最主要的数据是帖子的内容,用户也可以通过帖子的唯一ID或者帖子作者的名字来获取帖子。程序会通过将一个代表帖子的键映射至实际的 Post 结构来存储多个帖子。为了提供两种不同的方法来访问帖子,程序分别使用了两个 map 来创建两种不同的映射:

var PostById map[int]*Post
var PostsByAuthor map[string][]*Post

程序使用了两个变量来存储映射,其中 PostById 变量会将帖子的唯一ID映射至指向帖子的指针,而 PostsByAuthor 变量则会将作者的名字映射至一个切片,这个切片可以包含多个指向帖子的指针。注意,无论是 PostById 还是 PostsByAuthor ,它们映射的都是指向帖子的指针而不是帖子本身。这样做可以确保程序无论是通过ID还是通过作者的名字来获取帖子,得到的都是相同的帖子,而不是同一帖子的不同副本。

在此之后,程序定义了用于存储帖子的 store 函数:

func store(post Post) {
  PostById[post.Id] = &post
  PostsByAuthor[post.Author] = append(PostsByAuthor[post.Author], &post)
}

store 函数会将一个指向帖子的指针分别存储到 PostById 变量和 PostsByAuthor 变量里面。紧接着,在 main() 函数里面,程序创建了多个将要被存储的帖子,这个过程唯一要做的就是创建多个 Post 结构的实例:

post1 := Post{Id: 1, Content: "Hello World!", Author: "Sau Sheong"}
post2 := Post{Id: 2, Content: "Bonjour Monde!", Author: "Pierre"}
post3 := Post{Id: 3, Content: "Hola Mundo!", Author: "Pedro"}
post4 := Post{Id: 4, Content: "Greetings Earthlings!", Author: "Sau Sheong"}

接着程序会调用前面定义的 store 函数,把这些帖子一一存储起来:

store(post1)
store(post2)
store(post3)
store(post4)

如果运行这个程序,我们将会看到以下输出:

&{1 Hello World! Sau Sheong}
&{2 Bonjour Monde! Pierre}
&{1 Hello World! Sau Sheong}
&{4 Greetings Earthlings! Sau Sheong}
&{3 Hola Mundo! Pedro}

注意,无论程序是通过帖子的ID还是帖子的作者获取帖子,最终得到的都是同一个帖子。

这个例子看上去非常简单直接,甚至可以说有点儿简单过头了。我们之所以要学习怎样将数据存储在内存里面,是因为人们在构建Web应用的时候,常常会像第2章展示的那样,从一开始就使用关系数据库,然后在进行性能扩展的时候,才认识到自己需要将数据库返回的结果缓存起来以提高性能。正如本章接下来要介绍的内容所示,对数据进行持久化的绝大部分手段都会以这样或那样的形式使用结构,在学完本节介绍的方法之后,我们就可以在进行性能扩展的时候,通过重构代码来将缓存数据存储在内存里面,而不一定非得要使用类似Redis那样的外部内存数据库。

因为将数据存储到结构里面对数据存储操作是一种非常重要的重现手段,所以本章以及后续章节还会继续提及这一技术。

results matching ""

    No results matching ""